#include <stdio.h>
#include <math.h>
#include <stdbool.h>

// RGB结构体
typedef struct {
    int r, g, b;
} RGB;

// 方法1：欧几里得距离法
double euclidean_distance(RGB color1, RGB color2) {
    double dr = color1.r - color2.r;
    double dg = color1.g - color2.g;
    double db = color1.b - color2.b;
    
    return sqrt(dr*dr + dg*dg + db*db);
}

bool is_similar_euclidean(RGB color1, RGB color2, double threshold) {
    return euclidean_distance(color1, color2) <= threshold;
}

// 方法2：曼哈顿距离法
double manhattan_distance(RGB color1, RGB color2) {
    return abs(color1.r - color2.r) + 
           abs(color1.g - color2.g) + 
           abs(color1.b - color2.b);
}

bool is_similar_manhattan(RGB color1, RGB color2, double threshold) {
    return manhattan_distance(color1, color2) <= threshold;
}

// 方法4：加权欧几里得距离法（考虑人眼敏感度）
double weighted_euclidean_distance(RGB color1, RGB color2) {
    double dr = color1.r - color2.r;
    double dg = color1.g - color2.g;
    double db = color1.b - color2.b;
    
    // 人眼对绿色最敏感，红色次之，蓝色最不敏感
    return sqrt(2*dr*dr + 4*dg*dg + 3*db*db);
}

bool is_similar_weighted_euclidean(RGB color1, RGB color2, double threshold) {
    return weighted_euclidean_distance(color1, color2) <= threshold;
}

// 方法5：余弦相似度
double cosine_similarity(RGB color1, RGB color2) {
    // 计算点积
    double dot_product = color1.r * color2.r + 
                        color1.g * color2.g + 
                        color1.b * color2.b;
    
    // 计算向量长度
    double magnitude1 = sqrt(color1.r*color1.r + 
                           color1.g*color1.g + 
                           color1.b*color1.b);
    double magnitude2 = sqrt(color2.r*color2.r + 
                           color2.g*color2.g + 
                           color2.b*color2.b);
    
    // 避免除零
    if (magnitude1 == 0 || magnitude2 == 0) {
        return 0;
    }
    
    return dot_product / (magnitude1 * magnitude2);
}

bool is_similar_cosine(RGB color1, RGB color2, double threshold) {
    // 余弦相似度越接近1越相似，threshold通常设为0.95-0.99
    return cosine_similarity(color1, color2) >= threshold;
}

// 通用的颜色匹配函数
int find_closest_color(RGB target, RGB* reference_colors, int num_colors, int method) {
    int closest_index = 0;
    double best_score;
    
    switch(method) {
        case 1: // 欧几里得距离
            best_score = euclidean_distance(target, reference_colors[0]);
            for (int i = 1; i < num_colors; i++) {
                double score = euclidean_distance(target, reference_colors[i]);
                if (score < best_score) {
                    best_score = score;
                    closest_index = i;
                }
            }
            break;
            
        case 2: // 曼哈顿距离
            best_score = manhattan_distance(target, reference_colors[0]);
            for (int i = 1; i < num_colors; i++) {
                double score = manhattan_distance(target, reference_colors[i]);
                if (score < best_score) {
                    best_score = score;
                    closest_index = i;
                }
            }
            break;
            
        case 4: // 加权欧几里得距离
            best_score = weighted_euclidean_distance(target, reference_colors[0]);
            for (int i = 1; i < num_colors; i++) {
                double score = weighted_euclidean_distance(target, reference_colors[i]);
                if (score < best_score) {
                    best_score = score;
                    closest_index = i;
                }
            }
            break;
            
        case 5: // 余弦相似度
            best_score = cosine_similarity(target, reference_colors[0]);
            for (int i = 1; i < num_colors; i++) {
                double score = cosine_similarity(target, reference_colors[i]);
                if (score > best_score) { // 余弦相似度越大越好
                    best_score = score;
                    closest_index = i;
                }
            }
            break;
    }
    
    return closest_index;
}

// 示例主函数
int main() {
    // 定义一些参考颜色
    RGB reference_colors[] = {
        {255, 0, 0},    // 红色
        {0, 255, 0},    // 绿色
        {0, 0, 255},    // 蓝色
        {255, 255, 0},  // 黄色
        {255, 0, 255},  // 品红
        {0, 255, 255}   // 青色
    };
    int num_ref_colors = sizeof(reference_colors) / sizeof(RGB);
    
    // 测试颜色
    RGB test_colors[] = {
        {250, 10, 5},   // 接近红色
        {10, 250, 15},  // 接近绿色
        {128, 128, 128} // 灰色
    };
    int num_test_colors = sizeof(test_colors) / sizeof(RGB);
    
    printf("Color Similarity Test Results:\n");
    printf("===================\n");
    
    for (int i = 0; i < num_test_colors; i++) {
        printf("\nTest Color RGB(%d, %d, %d):\n", 
               test_colors[i].r, test_colors[i].g, test_colors[i].b);
        
        // 方法1：欧几里得距离
        int closest1 = find_closest_color(test_colors[i], reference_colors, num_ref_colors, 1);
        double dist1 = euclidean_distance(test_colors[i], reference_colors[closest1]);
        printf("Euclidean Distance: Closest color %d RGB(%d,%d,%d), distance=%.2f\n", 
               closest1, reference_colors[closest1].r, 
               reference_colors[closest1].g, reference_colors[closest1].b, dist1);
        
        // 方法2：曼哈顿距离
        int closest2 = find_closest_color(test_colors[i], reference_colors, num_ref_colors, 2);
        double dist2 = manhattan_distance(test_colors[i], reference_colors[closest2]);
        printf("Manhattan Distance: Closest color %d RGB(%d,%d,%d), distance=%.2f\n", 
               closest2, reference_colors[closest2].r, 
               reference_colors[closest2].g, reference_colors[closest2].b, dist2);
        
        // 方法4：加权欧几里得距离
        int closest4 = find_closest_color(test_colors[i], reference_colors, num_ref_colors, 4);
        double dist4 = weighted_euclidean_distance(test_colors[i], reference_colors[closest4]);
        printf("Weighted Euclidean Distance: Closest color %d RGB(%d,%d,%d), distance=%.2f\n", 
               closest4, reference_colors[closest4].r, 
               reference_colors[closest4].g, reference_colors[closest4].b, dist4);
        
        // 方法5：余弦相似度
        int closest5 = find_closest_color(test_colors[i], reference_colors, num_ref_colors, 5);
        double sim5 = cosine_similarity(test_colors[i], reference_colors[closest5]);
        printf("Cosine Similarity: Closest color %d RGB(%d,%d,%d), similarity=%.4f\n", 
               closest5, reference_colors[closest5].r, 
               reference_colors[closest5].g, reference_colors[closest5].b, sim5);
    }
    
    // 相似度判断示例
    printf("\n===================\n");
    printf("Similarity Judgment Example:\n");
    RGB color1 = {255, 0, 0};    // 红色
    RGB color2 = {250, 10, 5};   // 接近红色
    
    printf("Color 1: RGB(%d,%d,%d)\n", color1.r, color1.g, color1.b);
    printf("Color 2: RGB(%d,%d,%d)\n", color2.r, color2.g, color2.b);
    
    printf("Euclidean Distance Judgment (threshold 30): %s\n", 
           is_similar_euclidean(color1, color2, 30.0) ? "Similar" : "Not Similar");
    printf("Manhattan Distance Judgment (threshold 50): %s\n", 
           is_similar_manhattan(color1, color2, 50.0) ? "Similar" : "Not Similar");
    printf("Weighted Euclidean Distance Judgment (threshold 40): %s\n", 
           is_similar_weighted_euclidean(color1, color2, 40.0) ? "Similar" : "Not Similar");
    printf("Cosine Similarity Judgment (threshold 0.95): %s\n", 
           is_similar_cosine(color1, color2, 0.95) ? "Similar" : "Not Similar");
    
    return 0;
}